/*
 *  Copyright 2010 Mahbub Mozadded Sowrov.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package com.sowrov.afrigis.tools.timesheet;

import com.sowrov.afrigis.tools.timesheet.parse.html.ParseSubmitPage;
import com.sowrov.util.logsystem.ChronicleLogger;
import java.io.IOException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.xml.sax.SAXException;

/**
 * Write about the class here
 *
 * @author Mahbub Mozadded (Sowrov)
 * @date Apr 4, 2010
 */
public class TimeSheetClient {
    private static TimeSheetClient instance = null;
    private HttpClient tClient;

    private boolean loggedIn;

    private User user;
    
    private TimeSheetClient() {
        tClient = new HttpClient();
        tClient.getParams().setCookiePolicy(
                CookiePolicy.BROWSER_COMPATIBILITY);
        user = null;
        this.loggedIn = false;
    }

    public static TimeSheetClient getInstance() {
        if(TimeSheetClient.instance == null) {
            TimeSheetClient.instance = new TimeSheetClient();
        }
        return TimeSheetClient.instance;
    }

    public void setUser(User user) {
        if (user==null) {
            return;
        }
        this.user = user;
        int port = 80;
        try {
            port = Integer.parseInt(this.user.getPort());
        } catch(NumberFormatException ex) {
            port = 80;
        }
        tClient.getHostConfiguration().setHost(this.user.getUrl(), port, "http");
        this.loggedIn = false;
    }

    public boolean isLoggedIn() {
        return loggedIn;
    }

    public void setLoggedIn(boolean loggedIn) {
        this.loggedIn = loggedIn;
    }

    public synchronized int logIn() {
        if (user.getName().equals("") || user.getPassWord().equals("")) {
            return 0; //wrong id/password
        }
        try {
            PostMethod authpost = new PostMethod("/Default.asp");
            ChronicleLogger.getInstance().logDebug("Going to login "+user.getName()+" "+user.getPassWord());
            // Prepare login parameters
            NameValuePair action = new NameValuePair("action", "login");
            NameValuePair url = new NameValuePair("url", "/Default.asp");
            NameValuePair userid = new NameValuePair("Username", user.getName());
            NameValuePair password = new NameValuePair("Password", user.getPassWord());
            authpost.setRequestBody(new NameValuePair[]{action, url, userid, password});
            tClient.executeMethod(authpost);
            this.setLoggedIn(false);
            // release any connection resources used by the method
            authpost.releaseConnection();
            int ret = 0;
            if (authpost.getStatusCode() == 302) {
                ChronicleLogger.getInstance().logDebug("Login seem to be done.");
                String submitPage = this.getSubmitPage(""); //now lets check whether we can get the submit page
                if (submitPage.equals("") || submitPage.startsWith("<script")) {
                    ret = 0; //wrong id/password
                } else {
                    this.setLoggedIn(true);
                    ChronicleLogger.getInstance().logDebug("Login successful.");
                    ret = 1; //success
                }
                
            }
            else if (authpost.getStatusCode() == 200) {
                ret = 0; //wrong id/password
            }
            else {
                ChronicleLogger.getInstance().logCritical("Server unreachable "+authpost.getStatusCode());
                ret = -1; //server error
            }
            return ret;
        }
        catch (IOException ex) {
            ChronicleLogger.getInstance().logCritical("Ioexception "+ex.getMessage());
            return -1;//server error
        }
    }

    public synchronized String getSubmitPage(String date) {
        try {
            GetMethod getCall = new GetMethod("/timesheets/Default.asp?Edate="+date);
            tClient.executeMethod(getCall);
            String ret = "";
            ChronicleLogger.getInstance().logDebug("Getting page response status: "+getCall.getStatusCode()+" "+date);
            if (getCall.getStatusCode() == 200) {
                ret = getCall.getResponseBodyAsString().trim();
            }
            getCall.releaseConnection();
            return ret;
        }
        catch (HttpException ex) {
            ChronicleLogger.getInstance().logCritical("HttpException "+ex.getMessage());
            //Logger.getLogger(TimeSheetClient.class.getName()).log(Level.SEVERE, null, ex);
            return "";
        }
        catch (IOException ex) {
            ChronicleLogger.getInstance().logCritical("IOException "+ex.getMessage());
            //Logger.getLogger(TimeSheetClient.class.getName()).log(Level.SEVERE, null, ex);
            return "";
        }
    }

    public synchronized String  deletePost(String date, String id) {
        try {
            GetMethod getCall = new GetMethod("/timesheets/Default.asp?Edate="+date+"&Rec="+id+"&Type=Del");
            tClient.executeMethod(getCall);
            String ret = "";
            ChronicleLogger.getInstance().logDebug(getCall.getStatusCode()+" "+date);
            if (getCall.getStatusCode() == 200) {
                ret = getCall.getResponseBodyAsString().trim();
            }
            getCall.releaseConnection();
            return ret;
        }
        catch (HttpException ex) {
            ChronicleLogger.getInstance().logCritical("HttpException "+ex.getMessage());
            return "";
        }
        catch (IOException ex) {
            ChronicleLogger.getInstance().logCritical("IOException "+ex.getMessage());
            return "";
        }
    }

    public synchronized PostDataList submitPost(PostData post) throws IOException, SAXException {
        PostDataList newPostDataList = null;
        PostMethod postMethod = new PostMethod("/timesheets/Default.asp");
        // Prepare login parameters
        //action   = new NameValuePair("action", "post");
        NameValuePair urlP = new NameValuePair("url", "/Default.asp");
        NameValuePair projectP = new NameValuePair("Project", post.getProjectId()+"/"+post.getProjectRate());
        NameValuePair activityP = new NameValuePair("Activity", post.getActivityId());

        NameValuePair typeP = new NameValuePair("Type", "1");
        NameValuePair billAbleP = new NameValuePair("Billable", post.isBillable()?"1":"0");
        NameValuePair descriptionP = new NameValuePair("Description", post.getDescription());
        NameValuePair hourP = new NameValuePair("Hours", post.getDecimalTime());
        NameValuePair rateP = new NameValuePair("rate", "1");
        NameValuePair strDateP = new NameValuePair("edate", post.getStrDate());
        String projectDescription = User.getInstance().getProjectById(post.getProjectId()).getName();
        NameValuePair projDescriptionP = new NameValuePair("txtProjDescription", projectDescription);
        NameValuePair submitP = new NameValuePair("Submit", "Submit");
        NameValuePair dayTotal = new NameValuePair("DayTotal", "");
        NameValuePair dayTot = new NameValuePair("DayTot", "");
        //authpost.r
        postMethod.setRequestBody(new NameValuePair[]{
                    urlP, projectP, activityP, typeP, billAbleP, descriptionP,
                    hourP, rateP, strDateP, projDescriptionP, submitP, dayTotal, dayTot
                });
        //here we go
        this.tClient.executeMethod(postMethod);
//            System.out.println(postData.getResponseBodyAsString());
        ChronicleLogger.getInstance().logDebug("Data Submitted: " + postMethod.getStatusLine().toString());
        if (postMethod.getStatusCode() == 200) {
            //seem to be successfull but not 100% sure :|
            ParseSubmitPage parser = ParseSubmitPage.getInstance();

            parser.setHtmlCode(postMethod.getResponseBodyAsString(), post.getStrDate());
            parser.parse(true, false);
            newPostDataList = parser.getPostdataList();
        }
        // release any connection resources used by the method
        postMethod.releaseConnection();
        //return -1;
        return newPostDataList;
    }
    /**
     *
     * @param projectId "1049/250"
     * @param projectDescription "iSearch Project"
     * @param activityId "46"
     * @param type 1 / 2 / 3 (normal/overtime/weekend)
     * @param billAble 1 / 0 (Yes/No)
     * @param description "This is Description"
     * @param hour "1.5"
     * @param strDate "15/04/2010"
     * @return
     */
    public synchronized int submitAcitvity(String projectId, String projectDescription,
                                           String activityId, String type, String billAble, String description,
                                           String hour, String strDate) {

        try {
            PostMethod postData = new PostMethod("/timesheets/Default.asp");
            // Prepare login parameters
            //action   = new NameValuePair("action", "post");
            NameValuePair urlP = new NameValuePair("url", "/Default.asp");
            NameValuePair projectP = new NameValuePair("Project", projectId);
            //System.out.println(project);
            NameValuePair activityP = new NameValuePair("Activity", activityId);
            //System.out.println(activity);
            NameValuePair typeP = new NameValuePair("Type", "1");
            NameValuePair billAbleP = new NameValuePair("Billable", billAble);
            NameValuePair descriptionP = new NameValuePair("Description", description);
            //System.out.println(description);
            NameValuePair hourP = new NameValuePair("Hours", hour);
            //System.out.println(hour);
            NameValuePair rateP = new NameValuePair("rate", "1");
            NameValuePair strDateP = new NameValuePair("edate", strDate);
            //System.out.println(strDate);
            NameValuePair projDescriptionP = new NameValuePair("txtProjDescription", projectDescription);
            //System.out.println(projectDescription);
            NameValuePair submitP = new NameValuePair("Submit", "Submit");
            NameValuePair dayTotal = new NameValuePair("DayTotal", "");
            NameValuePair dayTot = new NameValuePair("DayTot", "");
            //authpost.r
            postData.setRequestBody(new NameValuePair[]{
                        urlP, projectP, activityP, typeP, billAbleP, descriptionP,
                        hourP, rateP, strDateP, projDescriptionP, submitP, dayTotal, dayTot
                    });
            this.tClient.executeMethod(postData);
//            System.out.println(postData.getResponseBodyAsString());
            ChronicleLogger.getInstance().logDebug("Data Submitted: " + postData.getStatusLine().toString());
            if (postData.getStatusCode() == 200) {
                return 1;
            }
            // release any connection resources used by the method
            postData.releaseConnection();
            return -1;
        }
        catch (IOException ex) {
            ChronicleLogger.getInstance().logCritical("IOException "+ex.getMessage());
            return -1;
        }
    }

    public static void main(String args[]) {
        TimeSheetClient timeSheet = new TimeSheetClient();
        User user = User.getInstance();
        user.setName("Mahbub");
        user.setPassWord("Sowrov");
        timeSheet.setUser(user);

        if (timeSheet.logIn() == 1) {
            System.out.println("Success");
        }
        else {
            System.out.println("Fail");
        }
        timeSheet.submitAcitvity("1049/250", "iSearch Project",
                                 "46", "1", "1", "Thi is Description", "1", "5/01/2011");
        /*timeSheet.setUser("Mahbub", "Sowrov");
        int login = timeSheet.logIn();
        if ( login == 1 ) {
        System.out.println("Successful");
        } else if (login == 0){
        System.out.println("UserName/Password missing");
        } else {
        System.out.println("Server failed");
        }*/
    }
}
